package localApplication;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.codec.binary.Base64;

import utils.AmazonConstants;
import utils.AmazonUtils;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.DeleteMessageRequest;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.amazonaws.util.StringInputStream;

public class LocalApp {

	public static void main(String[] args)  {
		
		
		
		if (args.length < 3){
			System.err.println("usege: <imageFilePath> <outputFile> <imagesPerWorker>");
			System.exit(-1);
		}
		int imagesPerWorker = 0;
		File imagesURLFile = null;
		try{ 
			imagesPerWorker = Integer.parseInt(args[2]);
		}catch (NumberFormatException e) {
			System.err.println("there was a number format exception tring to parse \"" + args[1] + "\"" );
			System.err.println(e.getMessage());
			e.printStackTrace();
			System.exit(-1);
		}
		try{
			imagesURLFile = new File(args[0]);
			if (imagesURLFile.createNewFile()){
				throw new IOException("file " + args[0] + " not found");
			}
		}catch (IOException e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			System.exit(-1);
		}
		String outputFile = args[1];
		AmazonS3Client s3 = null;
		AmazonEC2Client ec2 = null;
		AmazonSQSClient sqs = null;
		String jarS3URL = null;
		String imagesS3URL = null;
		String m2lqURL = null;
		String l2mqURL = null;
		String m2wqURL = null;
		String w2mqURL = null;
		Instance managerInstance = null;
		try{
			StringInputStream sip = new StringInputStream(AmazonConstants.AMAZON_CARDENTIALS);
			AWSCredentials credentials = new PropertiesCredentials(sip);
			s3 = new AmazonS3Client(credentials);
			ec2 = new AmazonEC2Client(credentials);
			sqs = new AmazonSQSClient(credentials);
			Region usWest2 = Region.getRegion(Regions.US_WEST_2);
			sqs.setRegion(usWest2);
//			ec2.setRegion(usWest2);
			s3.setRegion(usWest2);
//			ec2.setEndpoint("https://eu-west-1.ec2.amazonaws.com");
//			Bucket bucket = s3.getbucket(AmazonConstants.BUCKET_NAME);
			//uploading jar to s3
			
//			jarS3URL = AmazonUtils.uploadFileToS3(new File(AmazonConstants.JAR_LOCATION), s3, AmazonConstants.BUCKET_NAME, "jar");
//			System.out.println("done uploading jar file to : ");
//			System.out.println(jarS3URL);

			
			
			//uploading the images list
			imagesS3URL = AmazonUtils.uploadFileToS3(imagesURLFile, s3, AmazonConstants.BUCKET_NAME, "imagesList");
			
			//creating queueS
			m2lqURL = AmazonUtils.createQueue(sqs, AmazonConstants.MANAGER_2_LOCAL_QUEUE_NAME);
			l2mqURL = AmazonUtils.createQueue(sqs, AmazonConstants.LOCAL_2_MANAGER_QUEUE_NAME);
			m2wqURL = AmazonUtils.createQueue(sqs, AmazonConstants.MANAGER_2_WORKER_QUEUE_NAME);
			w2mqURL = AmazonUtils.createQueue(sqs, AmazonConstants.WORKER_2_MANAGER_QUEUE_NAME);
			
			sqs.sendMessage(new SendMessageRequest(l2mqURL, "new task " + imagesPerWorker + " imagesList"));
			//creating manager instance
			managerInstance = AmazonUtils.createInstances(1, 1, getManagerScript(jarS3URL, imagesS3URL, imagesPerWorker ), ec2, "manager").get(0);
			
			
			ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(m2lqURL);
			receiveMessageRequest.setVisibilityTimeout(2);
			receiveMessageRequest.setMaxNumberOfMessages(1);
		

			boolean shouldStop = false;
			while(!shouldStop ){
				List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
				if (!messages.isEmpty()){
					Message message = messages.get(0);
					String messageRecieptHandle = message.getReceiptHandle();
					sqs.deleteMessage(new DeleteMessageRequest(m2wqURL, messageRecieptHandle));
					shouldStop = true;
					
					
					System.out.println("  Message");
					System.out.println("    MessageId:     " + message.getMessageId());
					String body = message.getBody();
					System.out.println("    Body:          " + body);
					for (Entry<String, String> entry : message.getAttributes().entrySet()) 
					{
						System.out.println("  Attribute");
						System.out.println("    Name:  " + entry.getKey());
						System.out.println("    Value: " + entry.getValue());
					}
					if (body.startsWith("done task ")){
						String htmlFileKey = body.substring("done task ".length());
						S3Object result = AmazonUtils.readObjectFromS3(s3, AmazonConstants.BUCKET_NAME, htmlFileKey);
						StringBuilder htmlSB = AmazonUtils.readTextFromS3Object(result);
						FileOutputStream fos = new FileOutputStream(new File(outputFile));
						fos.write(htmlSB.toString().getBytes());
				        System.out.println(htmlSB.toString());
					}
	
				}else{
					Thread.sleep(3000);
				}
				
			}

			
		}catch (Exception e) {
			System.err.println("there was an error :" + e.getMessage());
			e.printStackTrace();
		}finally{
			try {
				Thread.sleep(6000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (ec2 != null){
				if (managerInstance != null){
					List<String> instances = new LinkedList<String>();
					instances.add(managerInstance.getInstanceId());
//					ec2.stopInstances(new StopInstancesRequest(instances));
				}
//				ec2.shutdown();
			}
			//shutting all down
			if (s3!= null){
//				s3.deleteObjects(new DeleteObjectsRequest(AmazonConstants.BUCKET_NAME));
//				s3.deleteBucket(new DeleteBucketRequest(AmazonConstants.BUCKET_NAME));
			}
			if (sqs != null){
				if (m2lqURL != null){
//					sqs.deleteQueue(new DeleteQueueRequest(m2lqURL));
				}
				if (l2mqURL != null){
//					sqs.deleteQueue(new DeleteQueueRequest(l2mqURL));
				}
				if (m2wqURL != null){
//					sqs.deleteQueue(new DeleteQueueRequest(m2wqURL));
				}
				if (w2mqURL != null){
//					sqs.deleteQueue(new DeleteQueueRequest(w2mqURL));
				}
			}
			
		}
	}

	
	
	private static String getManagerScript(String jarS3URL, String imagesS3URL, int imagesPerWorker){
		ArrayList<String> lines = new ArrayList<String>();
		lines.add("#! /bin/bash");
		if (jarS3URL==null){
			jarS3URL = "https://s3-us-west-2.amazonaws.com/ass1bucket/ass1.jar";
		}
		lines.add("wget "  + jarS3URL + " -O ass1.jar --no-check-certificate");
		lines.add("java -cp ass1.jar manager.Manager");
		lines.add("shutdown -h 0");
		String joinStrings = AmazonUtils.joinStrings(lines, "\n");
		String str = new String(Base64.encodeBase64(joinStrings.getBytes()));
		return str;
	}
	
	
	
}
